it('should be able to use eager mode', function () {
  function load(name) {
    return import(/* webpackMode: "eager" */ './dir1/' + name)
  }
  return testChunkLoading(load, true, true)
})

it('should be able to use lazy-once mode', function () {
  function load(name) {
    return import(/* webpackMode: "lazy-once" */ './dir2/' + name)
  }
  return testChunkLoading(load, false, true)
})

it('should be able to use lazy-once mode with name', function () {
  function load(name) {
    return import(
      /* webpackMode: "lazy-once", webpackChunkName: "name-lazy-once" */ './dir3/' +
        name
    )
  }
  return testChunkLoading(load, false, true)
})

it('should be able to use lazy mode', function () {
  function load(name) {
    return import(/* webpackMode: "lazy" */ './dir4/' + name)
  }
  return testChunkLoading(load, false, false)
})

it('should be able to use lazy mode with name', function () {
  function load(name) {
    return import(
      /* webpackMode: "lazy", webpackChunkName: "name-lazy" */ './dir5/' + name
    )
  }
  return testChunkLoading(load, false, false)
})

it('should be able to use lazy mode with name and placeholder', function () {
  function load(name) {
    return import(
      /* webpackMode: "lazy", webpackChunkName: "name-lazy-[request]" */ './dir6/' +
        name
    )
  }
  return testChunkLoading(load, false, false)
})

it('should be able to combine chunks by name', function () {
  function load(name) {
    switch (name) {
      case 'a':
        return import(/* webpackMode: "eager" */ './dir7/a')
      case 'b':
        return import(/* webpackChunkName: "name-3" */ './dir7/b')
      case 'c':
        return import(/* webpackChunkName: "name-3" */ './dir7/c')
      case 'd':
        return import(/* webpackChunkName: "name-3" */ './dir7/d')
      default:
        throw new Error('Unexpected test data')
    }
  }
  return testChunkLoading(load, false, true)
})

it('should be able to use weak mode', function () {
  function load(name) {
    return import(/* webpackMode: "weak" */ './dir8/' + name)
  }
  require('./dir8/a') // chunks served manually by the user
  require('./dir8/b')
  require('./dir8/c')
  return testChunkLoading(load, true, true)
})

it('should be able to use weak mode (without context)', function () {
  function load(name) {
    switch (name) {
      case 'a':
        return import(/* webpackMode: "weak" */ './dir9/a')
      case 'b':
        return import(/* webpackMode: "weak" */ './dir9/b')
      case 'c':
        return import(/* webpackMode: "weak" */ './dir9/c')
      default:
        throw new Error('Unexpected test data')
    }
  }
  require('./dir9/a') // chunks served manually by the user
  require('./dir9/b')
  require('./dir9/c')
  return testChunkLoading(load, true, true)
})

it('should not find module when mode is weak and chunk not served elsewhere', function () {
  var name = 'a'
  return import(/* webpackMode: "weak" */ './dir10/' + name).catch(
    function (e) {
      expect(e).toMatchObject({
        message: /not available/,
        code: /MODULE_NOT_FOUND/,
      })
    }
  )
})

it('should not find module when mode is weak and chunk not served elsewhere (without context)', function () {
  return import(/* webpackMode: "weak" */ './dir11/a').catch(function (e) {
    expect(e).toMatchObject({
      message: /not available/,
      code: /MODULE_NOT_FOUND/,
    })
  })
})

if (process.env.NODE_ENV === 'production') {
  it('should contain only one export from webpackExports from module', function () {
    return import(/* webpackExports: "usedExports" */ './dir12/a?1').then(
      (module) => {
        expect(module.usedExports).toEqual(['usedExports'])
      }
    )
  })

  it('should contain only webpackExports from module', function () {
    return import(
      /* webpackExports: ["a", "usedExports", "b"] */ './dir12/a?2'
    ).then((module) => {
      expect(module.usedExports).toEqual(['a', 'b', 'usedExports'])
    })
  })

  it('should contain only webpackExports from module in eager mode', function () {
    return import(
      /*
			webpackMode: "eager",
			webpackExports: ["a", "usedExports", "b"]
		*/ './dir12/a?3'
    ).then((module) => {
      expect(module.usedExports).toEqual(['a', 'b', 'usedExports'])
    })
  })

  it('should contain webpackExports from module in weak mode', function () {
    require.resolve('./dir12/a?4')
    return import(
      /*
			webpackMode: "weak",
			webpackExports: ["a", "usedExports", "b"]
		*/ './dir12/a?4'
    ).then((module) => {
      expect(module.usedExports).toEqual(['a', 'b', 'usedExports'])
    })
  })

  it('should not mangle webpackExports from module', function () {
    return import(/* webpackExports: "longnameforexport" */ './dir12/a?5').then(
      (module) => {
        expect(module).toHaveProperty('longnameforexport')
      }
    )
  })

  it('should not mangle default webpackExports from module', function () {
    return import(/* webpackExports: "default" */ './dir12/a?6').then(
      (module) => {
        expect(module).toHaveProperty('default')
      }
    )
  })

  it('should contain only webpackExports from module in context mode', function () {
    const x = 'b'
    return import(/* webpackExports: "usedExports" */ `./dir13/${x}`).then(
      (module) => {
        expect(module.usedExports).toEqual(['usedExports'])
      }
    )
  })
}

function testChunkLoading(load, expectedSyncInitial, expectedSyncRequested) {
  var sync = false
  var syncInitial = true
  var p = Promise.all([load('a'), load('b')]).then(function () {
    expect(syncInitial).toBe(expectedSyncInitial)
    sync = true
    var p = Promise.all([
      load('a').then(function (a) {
        expect(a).toEqual(
          nsObj({
            default: 'a',
          })
        )
        expect(sync).toBe(true)
      }),
      load('c').then(function (c) {
        expect(c).toEqual(
          nsObj({
            default: 'c',
          })
        )
        expect(sync).toBe(expectedSyncRequested)
      }),
    ])
    Promise.resolve()
      .then(function () {})
      .then(function () {})
      .then(function () {})
      .then(function () {
        sync = false
      })
    return p
  })
  Promise.resolve()
    .then(function () {})
    .then(function () {})
    .then(function () {})
    .then(function () {
      syncInitial = false
    })
  return p
}
